package com.dries.portal.module.coupon.executor;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.dries.portal.module.coupon.vo.CouponTemplateSDK;
import com.dries.portal.module.coupon.vo.GoodsInfo;
import com.dries.portal.module.coupon.vo.SettlementInfo;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 规则执行器抽象类，定义通用方法
 * @Author ZSY
 * @createTime 2020/7/31 13:33
 */
@Slf4j
public abstract class AbstractExecutor {

    /**
     * 校验商品类型与优惠券是否匹配
     * 1. 这里实现的单品类优惠券的校验，多品类优惠券重载此方法
     * 2. 商品只需要有一个优惠券要求的商品类型去匹配就可以
     *
     * @param settlementInfo
     * @return
     */
    protected boolean isGoodsTypeSatisfy(SettlementInfo settlementInfo) {

        List<Integer> goodsType = settlementInfo.getGoodsInfos()
                .stream().map(GoodsInfo::getType)
                .collect(Collectors.toList());
        List<Integer> temGoodsType = JSONUtil.toList(
                JSONUtil.parseArray(settlementInfo.getCouponAndTemplateInfos().get(0)
                        .getTemplate().getRule().getUsage().getGoodsType()),
                Integer.class
        );

        // 存在交集即可
        return CollUtil.isNotEmpty(CollUtil.intersection(goodsType, temGoodsType));
    }

    /**
     * 处理商品类型与优惠券限制不匹配的情况
     *
     * @param settlementInfo
     * @param goodsSum
     * @return
     */
    protected SettlementInfo processGoodsTypeNotSatisfy(SettlementInfo settlementInfo, BigDecimal goodsSum) {
        boolean isGoodsTypeSatify = isGoodsTypeSatisfy(settlementInfo);
        // 当商品类型不满足时，直接返回总价，并清空优惠券
        if (!isGoodsTypeSatify) {
            settlementInfo.setCost(goodsSum);
            settlementInfo.setCouponAndTemplateInfos(Collections.emptyList());

            return settlementInfo;
        }

        return null;
    }

    /**
     * 商品总价
     */
    protected BigDecimal goodsCostSum(List<GoodsInfo> goodsInfos) {

        return goodsInfos.stream().map(
                e -> {
                    BigDecimal amount = new BigDecimal(e.getCount());
                    return e.getPrice().multiply(amount);
                }
        ).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 商品总价是否满足优惠券基准
     */
    protected SettlementInfo checkBase(BigDecimal goodsSum, SettlementInfo settlement) {
        // 折扣优惠券可以直接使用（门槛基准可有可无）
        CouponTemplateSDK sdk = settlement.getCouponAndTemplateInfos().get(0).getTemplate();
        // 满减
        BigDecimal base = sdk.getRule().getDiscount().getBase();
        // 如果不符合，则直接返回商品总价
        if (goodsSum.compareTo(base) < 0) {
            log.info("当前商品总价不符合优惠券使用要求");
            settlement.setCost(goodsSum);
            settlement.setCouponAndTemplateInfos(Collections.emptyList());

            return settlement;
        }
        return null;
    }

    /**
     * 保留两位小数
     */
    protected double retain2Decimals(double value) {
        return new BigDecimal(value).setScale(
                2, BigDecimal.ROUND_HALF_UP
        ).doubleValue();
    }

    protected BigDecimal retain2BigDecimals(BigDecimal value) {
        return value.setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 最小支付费用
     */
    protected double minCost() {
        return 0.1;
    }

    protected BigDecimal minCostBigDecimal() {
        return new BigDecimal("0.1");
    }

}
